﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SmartProject.Data;

using NHibernate;
using NHibernate.Criterion;

namespace SmartProject.Entity
{
    public class Log : EntityBase
    {
        public virtual string ClassName { get; set; }

        public virtual string MethodName { get; set; }

        public virtual string Description { get; set; }

        public virtual Severity Severity { get; set; }

        /// <summary>
        /// Get a list of log entries based on the severity level.
        /// </summary>
        /// <param name="session">Session used in this request.</param>
        /// <param name="severityLevel">Severity level.</param>
        /// <returns>IList of logs.</returns>
        public static IList<Log> GetLogs(ISession session, string severityLevel)
        {
            IList<Log> logs = new List<Log>();
            IList<ICriterion> expressions = new List<ICriterion>();
            expressions.Add(Restrictions.Eq("Severity", Severity.GetSeverity(session, severityLevel)));
            IList<Order> orderings = new List<Order>();
            orderings.Add(Order.Desc("Created"));
            IList<EntityBase> entities = Find(session, expressions, orderings, typeof(Log));
            for (int i = 0; i < entities.Count; i++)
            {
                logs.Add((Log)entities[i]);
            }
            return logs;
        }

        /// <summary>
        /// Logs the exception.
        /// </summary>
        /// <param name="session">Session used in this request.</param>
        /// <param name="classInstance"></param>
        /// <param name="exception"></param>
        public static void Exception(ISession session, object classInstance, Exception exception)
        {
            LogBase(session, classInstance, exception.Source, exception.Message, "Exception");
        }


        public static void Error(ISession session, object classInstance, string methodName, string description)
        {
            LogBase(session, classInstance, methodName, description, "Error");
        }

        public static void Warn(ISession session, object classInstance, string methodName, string description)
        {
            LogBase(session, classInstance, methodName, description, "Warn");
        }

        public static void Debug(ISession session, object classInstance, string methodName, string description)
        {
            LogBase(session, classInstance, methodName, description, "Debug");
        }

        public static void Info(ISession session, object classInstance, string methodName, string description)
        {
            LogBase(session, classInstance, methodName, description, "Info");
        }

        /// <summary>
        /// Base method to log messages.
        /// </summary>
        /// <param name="session">Session used in this request.</param>
        /// <param name="classInstance"></param>
        /// <param name="methodName"></param>
        /// <param name="description"></param>
        /// <param name="severityLevel"></param>
        private static void LogBase(ISession session, object classInstance, string methodName, string description, string severityLevel)
        {
            var logSeverity = Severity.GetSeverity(session, severityLevel);
            var preferred = GetPreferredSeverity(session);

            if (preferred != null)
            {
                if (logSeverity.Level < preferred.Level)
                {
                    return;
                }
            }

            Log log = new Log();
            if (classInstance.GetType() == typeof(String))
            {
                log.ClassName = (string)classInstance;
            }
            else
            {
                log.ClassName = classInstance.GetType().ToString();
            }
            log.MethodName = methodName;
            log.Description = description;
            log.Severity = logSeverity;
            log.Save(session);
        }

        /// <summary>
        /// Deletes the inactive ProductCategory instances.
        /// </summary>
        /// <param name="session">Session used in this request.</param>
        public static void Clean(ISession session)
        {
            Delete(session, typeof(Log));
        }

        public static Severity GetPreferredSeverity(ISession session)
        {
            var preference = Preference.GetPreference(session, "LoggingLevel");
            if (preference == null)
            {
                return null;
            }

            if (!String.IsNullOrEmpty(preference.PrefValue))
            {
                return Severity.GetSeverity(session, Convert.ToInt32(preference.PrefValue));
            }
            return null;
        }

        /// <summary>
        /// Sets the preferred severity level.
        /// </summary>
        /// <param name="session">Session used in this request.</param>
        /// <param name="severity"></param>
        public static void SetPreferredSeverity(ISession session, Severity severity)
        {
            var preference = Preference.GetPreference(session, "LoggingLevel");
            if (preference == null)
            {
                preference = new Preference();
                preference.PrefName = "LoggingLevel";
            }
            preference.PrefValue = severity.Id.ToString();
            preference.Save(session);
        }
    }
}
